import { showNoneIconToast } from './toast'
import request from './request'

import { getAvatarUploadSignApi } from '@/api/user.js'
/**
 * 手机上常见的图片扩展名
 */
 const imageExtName = ['png', 'jpeg', 'jpg', 'bmp', 'raw']
/**
 * 手机上常见的音频扩展名
 */ const audioExtName = ['mp3', 'wav', 'aac', 'flac', 'ogg']
/**
 * 手机上常见的视频扩展名
 */
 const videoExtName = [
  'mp4',
  'avi',
  'flv',
  'mov',
  '3gp',
  'mkv',
  'rmvb'
]
/**
 * 选择文件或拍摄
 */
export const chooseFile = ({ count, mediaType, sourceType }) => {
  return new Promise((resolve, reject) => {
    // 检查API支持情况
    const hasChooseMedia = typeof uni.chooseMedia === 'function'
    const chooseMethod = hasChooseMedia ? 'chooseMedia' : 'chooseImage'
    
    const params = {
      count,
      sourceType,
      success: async (res) => {
        let tempFiles = []
        
        if (chooseMethod === 'chooseMedia') {
          tempFiles = res.tempFiles
        } else {
          tempFiles = res.tempFilePaths.map(path => ({
            tempFilePath: path,
            size: 0
          }))
        }
        
        if (!tempFiles.length) {
          resolve(null)
          return
        }
        
        // 如果count为1，返回单个文件路径；否则返回文件路径数组
        if (count === 1) {
          const [{ tempFilePath, size: reportedSize }] = tempFiles
          
          try {
            let actualSize = reportedSize
            
            // 使用uni.getFileInfo获取准确文件大小
            if (typeof uni.getFileInfo === 'function') {
              const fileInfo = await new Promise((resolve, reject) => {
                uni.getFileInfo({
                  filePath: tempFilePath,
                  success: resolve,
                  fail: reject
                })
              })
              actualSize = fileInfo.size
            }
            
            // 5MB限制检查
            const maxSize = 5 * 1024 * 1024
            if (actualSize > maxSize) {
              const sizeInMB = (actualSize / (1024 * 1024)).toFixed(2)
              showNoneIconToast(`文件大小不能超过5MB (当前${sizeInMB}MB)`)
              resolve(null)
              return
            }
            
            resolve(tempFilePath)
            
          } catch (error) {
            // 获取文件大小失败时使用原始大小
            const maxSize = 5 * 1024 * 1024
            if (reportedSize > maxSize) {
              const sizeInMB = (reportedSize / (1024 * 1024)).toFixed(2)
              showNoneIconToast(`文件大小不能超过5MB (当前${sizeInMB}MB)`)
              resolve(null)
              return
            }
            resolve(tempFilePath)
          }
        } else {
          // 多文件选择，返回文件路径数组
          const filePaths = tempFiles.map(file => file.tempFilePath)
          resolve(filePaths)
        }
      },
      fail: (error) => {
        showNoneIconToast(error.errMsg || '文件选择失败')
        reject(new Error(error.errMsg || '文件选择失败'))
      }
    }
    
    // 媒体类型处理
    if (chooseMethod === 'chooseMedia') {
      params.mediaType = mediaType
    } else if (mediaType && mediaType.includes('video')) {
      // 视频选择
      uni.chooseVideo({
        sourceType,
        success: async (res) => {
          if (!res.tempFilePath) {
            resolve(null)
            return
          }
          
          try {
            let actualSize = 0
            if (typeof uni.getFileInfo === 'function') {
              const fileInfo = await new Promise((resolve, reject) => {
                uni.getFileInfo({
                  filePath: res.tempFilePath,
                  success: resolve,
                  fail: reject
                })
              })
              actualSize = fileInfo.size
            }
            
            const maxSize = 5 * 1024 * 1024
            if (actualSize > maxSize) {
              const sizeInMB = (actualSize / (1024 * 1024)).toFixed(2)
              showNoneIconToast(`视频大小不能超过5MB (当前${sizeInMB}MB)`)
              resolve(null)
              return
            }
            
            resolve(res.tempFilePath)
          } catch (error) {
            resolve(res.tempFilePath)
          }
        },
        fail: (error) => {
          showNoneIconToast(error.errMsg || '视频选择失败')
          reject(new Error(error.errMsg || '视频选择失败'))
        }
      })
      return
    }
    
    uni[chooseMethod](params)
  })
}
/**
 * 生成 uuid
 */
export function createUUID() {
  let dt = Date.now()
  const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
    /[xy]/g,
    (c) => {
      const r = (dt + Math.random() * 16) % 16 | 0
      dt = Math.floor(dt / 16)
      return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16)
    }
  )
  return uuid
}

/**
 * 从路径获取扩展名
 */
const getExtFromPath = (filePath) => {
  const lastDotIndex = filePath.lastIndexOf('.')
  if (lastDotIndex !== -1) {
    return filePath.slice(lastDotIndex)
  }
  return ''
}

/**
 * 获取文件类型
 */
const getFileType = (tempFilePath) => {
  // 拿到文件扩展名，比如：.png，.jpeg等
  const extName = tempFilePath.slice(
    tempFilePath.lastIndexOf('.') + 1
  )
  // 判断
  let fileType = null
  if (imageExtName.includes(extName)) {
    fileType = 'image'
  } else if (audioExtName.includes(extName)) {
    fileType = 'audio'
  } else if (videoExtName.includes(extName)) {
    fileType = 'video'
  }
  return fileType
}
/**
 * 检测是否为H5平台
 */
const isH5Platform = () => {
  // 检测是否在浏览器环境
  return typeof window !== 'undefined' && window.location && window.location.protocol.startsWith('http')
}

/**
 * 从MIME类型获取扩展名
 */
const getExtFromMime = (mimeType) => {
  const mimeMap = {
    'image/jpeg': '.jpg',
    'image/jpg': '.jpg', 
    'image/png': '.png',
    'image/gif': '.gif',
    'image/webp': '.webp',
    'image/bmp': '.bmp',
    'video/mp4': '.mp4',
    'video/quicktime': '.mov',
    'video/x-msvideo': '.avi',
    'video/webm': '.webm',
    'application/pdf': '.pdf',
    'application/msword': '.doc',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
    'text/plain': '.txt',
    'application/json': '.json'
  }
  return mimeMap[mimeType] || '.bin'
}

/**
 * H5平台文件上传处理
 * 使用XMLHttpRequest进行真实上传，解决CORS问题
 */
export const uploadFileH5 = async (tempFilePath, signRes) => {
  return new Promise((resolve, reject) => {
    const { url, formData: signFormData } = signRes
    
    // 获取文件并添加到FormData
    fetch(tempFilePath)
      .then(response => response.blob())
      .then(blob => {
        // 从blob的MIME类型获取正确的扩展名
        const extName = getExtFromMime(blob.type)
        const fileName = createUUID() + extName
        
        // 创建FormData对象
        const formData = new FormData()
        
        // 添加签名返回的所有formData字段
        Object.keys(signFormData).forEach(key => {
          formData.append(key, signFormData[key])
        })
        
        // 添加文件到file字段
        formData.append('file', blob, fileName)
        
        // 使用XMLHttpRequest进行上传
        const xhr = new XMLHttpRequest()
        xhr.open('POST', url, true)
        
        xhr.onload = () => {
          if (xhr.status === 200 || xhr.status === 204) {
            resolve(signRes.accessPath)
          } else {
            reject(new Error(`上传失败: ${xhr.status}`))
          }
        }
        
        xhr.onerror = () => {
          reject(new Error('网络错误，请检查CORS配置'))
        }
        
        xhr.send(formData)
      })
      .catch(error => {
        reject(new Error('文件读取失败: ' + error.message))
      })
  })
}

/**
 * 把临时文件路径上传至文件服务器
 * 支持多种文件存储服务器（OSS、S3等）
 * @param {string} tempFilePath - 临时文件路径
 * @param {string} type - 上传类型：'avatar' 或 'company'
 * @param {Function} signApi - 获取签名的API函数
 */
export const uploadFile2OSS = (tempFilePath, type = 'avatar', signApi = getAvatarUploadSignApi) => {
  return new Promise(async (resolve, reject) => {
    try {
      const isH5 = isH5Platform()
      
      // 每次上传都获取新的签名（不缓存）
      const signRes = await signApi()
      const { url, formData: signFormData, accessPath } = signRes

      // H5平台使用XMLHttpRequest上传，其他平台使用uni.uploadFile
      if (isH5) {
        try {
          const result = await uploadFileH5(tempFilePath, signRes)
          resolve(result)
        } catch (error) {
          showNoneIconToast('上传失败: ' + error.message)
          reject(error)
        }
        return
      }
      
      // 原生平台使用uni.uploadFile
      uni.uploadFile({
        url: url,
        filePath: tempFilePath,
        name: 'file',
        fileType: getFileType(tempFilePath),
        formData: signFormData,
        success: (res) => {
          if (res.statusCode === 200 || res.statusCode === 204) {
            resolve(accessPath)
          } else {
            showNoneIconToast('上传失败')
            reject(new Error('上传失败'))
          }
        },
        fail: (error) => {
          showNoneIconToast('上传失败')
          reject(error)
        },
        complete: () => {
          uni.hideLoading({
            fail: () => {}
          })
        }
      })
    } catch (e) {
      // showNoneIconToast('上传初始化失败')
      reject(e)
    }
  })
}
